package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.heima.common.constants.WemediaConstants;
import com.heima.feign.article.IArtileFeignClient;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.pojos.WmChannel;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmSensitive;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.utils.common.SensitiveWordUtil;
import com.heima.wemedia.mapper.WmChannelMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmSensitiveMapper;
import com.heima.wemedia.mapper.WmUserMapper;
import com.heima.wemedia.service.GreenScanService;
import com.heima.wemedia.service.WmNewsAutoScanService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
@Transactional
public class WmNewsAutoScanServiceImpl implements WmNewsAutoScanService {

    @Autowired
    private WmNewsMapper wmNewsMapper;
    @Autowired
    private GreenScanService greenScanService;
    @Autowired
    private WmChannelMapper wmChannelMapper;
    @Autowired
    private WmUserMapper wmUserMapper;
    @Autowired
    private IArtileFeignClient iArtileFeignClient;
    @Autowired
    private WmSensitiveMapper wmSensitiveMapper;
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 文章内容图片自动审核
     *
     * @param id
     */
    @Override
    //表名当前为异步方法：
    //@Async //底层使用了线性池
    public void newAutoScan(Integer id) {
        //查询数据：
        WmNews wmNews = wmNewsMapper.selectById(id);
        //数据校验：
        if (wmNews == null) {
            //返回参数缺失
            throw new RuntimeException("查询不到文章");
        }

        //文章处于待审核状态
        if (wmNews.getStatus() == WmNews.Status.SUBMIT.getCode()) {
            //提取文章的图片和文章内容：
            Map<String, Object> textAndImage = getTextAndImage(wmNews);

            //审核文字,不通过需要修改文章状态

            //自管理审核：
            boolean sensitiveScan = getSensitiveScan((String) textAndImage.get("text"), wmNews);
            //boolean sensitiveScan = true;
            if (!sensitiveScan) return;
            //百度云审核，方法中有有OCR审核图片中文字内容
            boolean scanText = getScanText((String) textAndImage.get("text"), wmNews);
            //boolean scanText = true;
            //审核失败，退出
            if (!scanText) return;

            //审核图片
            boolean scanImage = getScanImage((List<String>) textAndImage.get("image"), wmNews);
            //boolean scanImage = true;
            if (!scanImage) return;

            try {
                //文章数据保存到APP端
                ResponseResult result = saveAppArtile(wmNews);
                //判断获取返回的Code
                if (result.getCode() == 200) {
                    //获取返回的值：ap端文章的 id   ArtileID
                    wmNews.setArticleId((long) result.getData());
                    //更改文章状态为发布状态：9
                    wmNews.setStatus(WmNews.Status.PUBLISHED.getCode());
                    //设置文章通过内容
                    wmNews.setReason("审核通过");
                    //更新数据
                    wmNewsMapper.updateById(wmNews);
                } else {
                    //抛出异常：
                    throw new RuntimeException("数据同步APP端失败！");
                }
            } catch (RuntimeException e) {
                e.printStackTrace();
                throw new RuntimeException("数据同步APP端失败！");
            }

        }

    }

    /**
     * 自管理敏感词查询
     *
     * @param text
     * @param wmNews
     * @return 获取自定义敏感词集合
     * 使用工具类将 自定义敏感词集合 设置为 敏感词词库
     * 使用工具类将 传过来的 文本 进行审核  返回map
     * map有数据 为审核失败  修改文章状态
     */
    public boolean getSensitiveScan(String text, WmNews wmNews) {
        boolean flag = true;

        //先从Redis中获取：
        List<String> sensitiveList = (List<String>) redisTemplate.opsForValue().get("Sensitive");
        if (sensitiveList == null || sensitiveList.size() == 0) {
            //redis中没有数据
            //从数据库中获取所有的敏感词
            List<WmSensitive> wmSensitives = wmSensitiveMapper.selectList(Wrappers.<WmSensitive>lambdaQuery().select(WmSensitive::getSensitives));
            sensitiveList = wmSensitives.stream().map(WmSensitive::getSensitives).collect(Collectors.toList());
            //数据存入Redis
            redisTemplate.opsForValue().set("Sensitive", sensitiveList);
        }

        //初始化敏感词库
        SensitiveWordUtil.initMap(sensitiveList);

        //查看文章中是否包含敏感词
        Map<String, Integer> map = SensitiveWordUtil.matchWords(text);
        if (map.size() > 0 && wmNews != null) {
            //修改文章状态：
            wmNews.setStatus(WmNews.Status.FAIL.getCode());
            wmNews.setReason("文字存在违规" + map);
            //修改文章
            wmNewsMapper.updateById(wmNews);
            flag = false;
        } else if (map.size() > 0 && wmNews == null) {
            flag = false;
        }

        return flag;

    }

    /**
     * 保存文章到AP端
     *
     * @param wmNews
     */
    public ResponseResult saveAppArtile(WmNews wmNews) {
        //准备数据：
        ArticleDto articleDto = new ArticleDto();
        //拷贝数据（部分）
        BeanUtils.copyProperties(wmNews, articleDto);
        //补全数据：
        //文章布局
        articleDto.setLayout(wmNews.getType());
        //频道
        WmChannel wmChannel = wmChannelMapper.selectById(wmNews.getChannelId());
        if (wmChannel != null) {
            articleDto.setChannelName(wmChannel.getName());
        }
        //作者：
        //作者ID
        articleDto.setAuthorId(wmNews.getUserId().longValue());
        //作者姓名
        WmUser wmUser = wmUserMapper.selectById(wmNews.getUserId());
        if (wmUser != null) {
            articleDto.setAuthorName(wmUser.getName());
        }
        //设置文章ID：如果存在就走修改，反之新增
        if (wmNews.getArticleId() != null) {
            articleDto.setId(wmNews.getArticleId());
        }
        //创建时间：
        articleDto.setCreatedTime(new Date());

        ResponseResult result = iArtileFeignClient.saveArticle(articleDto);

        return result;

    }

    /**
     * 审核图片
     *
     * @param image
     * @param wmNews
     * @return
     */
    private boolean getScanImage(List<String> image, WmNews wmNews) {
        boolean flag = true;

        //图片去重
        image = image.stream().distinct().collect(Collectors.toList());

        //遍历图片
        for (String imageURL : image) {
            try {
                Map map = greenScanService.scanImage(imageURL);
                //不通过：
                if (map.get("conclusionType") == WemediaConstants.BAIDU_SCAN_NOPASS) {
                    flag = false;
                    //修改文章状态：
                    wmNews.setStatus(WmNews.Status.FAIL.getCode());
                    wmNews.setReason("审核不通过,图片违规");
                    //修改文章
                    wmNewsMapper.updateById(wmNews);
                    break;
                }
                //疑似：人工审核
                if (map.get("conclusionType") == WemediaConstants.BAIDU_SCAN_YS) {
                    flag = false;
                    //修改文章状态：
                    wmNews.setStatus(WmNews.Status.ADMIN_AUTH.getCode());
                    wmNews.setReason("图片疑似违规，人工审核");
                    //修改文章
                    wmNewsMapper.updateById(wmNews);
                    break;
                }

            } catch (Exception e) {
                e.printStackTrace();
                flag = false;
            }
        }
        return flag;
    }

    /**
     * 文字审核
     *
     * @param text
     * @param wmNews
     * @return
     */
    private boolean getScanText(String text, WmNews wmNews) {
        boolean flag = true;
        try {
            Map map = greenScanService.scanText(text);
            //不通过：
            if (map.get("conclusionType") == WemediaConstants.BAIDU_SCAN_NOPASS) {
                flag = false;
                //修改文章状态：
                wmNews.setStatus(WmNews.Status.FAIL.getCode());
                wmNews.setReason("文字审核不通过");
                //修改文章
                wmNewsMapper.updateById(wmNews);
            }
            //疑似：人工审核
            if (map.get("conclusionType") == WemediaConstants.BAIDU_SCAN_YS) {
                flag = false;
                //修改文章状态：
                wmNews.setStatus(WmNews.Status.ADMIN_AUTH.getCode());
                wmNews.setReason("文字疑似，人工审核");
                //修改文章
                wmNewsMapper.updateById(wmNews);
            }

        } catch (Exception e) {
            e.printStackTrace();
            flag = false;
        }
        return flag;
    }

    /**
     * 获取文章内容和图片
     *
     * @param wmNews
     * @return
     */
    private Map<String, Object> getTextAndImage(WmNews wmNews) {
        //文章内容，标题，封面图片
        String content = wmNews.getContent();
        String coverImages = wmNews.getImages();
        String title = wmNews.getTitle();

        //存放文字的容器
        StringBuilder stringBuilder = new StringBuilder();
        //存放图片的容器
        List<String> images = new ArrayList();

        //校验参数：
        if (StringUtils.isNotEmpty(content) ||
                StringUtils.isNotEmpty(coverImages) ||
                StringUtils.isNotEmpty(title)) {

            //校验参数：文章内容不为空：
            if (StringUtils.isNotEmpty(content)) {
                //获取章内容的图片的文字
                //转为JSON数组
                JSONArray jsonArray = JSON.parseArray(content);

                //遍历：
                for (Object json : jsonArray) {
                    //转为JsonObject
                    JSONObject jsonObject = JSON.parseObject(json.toString());
                    if (jsonObject.get("type").equals("text")) {
                        stringBuilder.append(jsonObject.get("value").toString());
                    }
                    if (jsonObject.get("type").equals("image")) {
                        images.add((String) jsonObject.get("value"));
                    }
                }
            }

            //如果文章封面图片不为空：加入容器：
            if (StringUtils.isNotEmpty(coverImages)) {
                //根据” , “拆分成数组：
                String[] split = coverImages.split(",");
                //数组全部加入集合：
                images.addAll(Arrays.asList(split));
            }
            //如果文章标题不为空：加入文本容器
            if (StringUtils.isNotEmpty(title)) {
                stringBuilder.append(wmNews.getTitle());
            }

            Map<String, Object> map = new HashMap<>();
            map.put("text", stringBuilder.toString());
            map.put("image", images);
            return map;
        }
        return null;
    }
}
